use std::sync::Arc;
use axum::{routing::{get, post}, Router, Json};
use axum::extract::{Path, State};
use tempfile::NamedTempFile;
use week4_homework::dao::UrlDAO;


#[derive(serde::Serialize, serde::Deserialize)]
struct UrlShorten {
    url: String,
    short_url: String,
}

#[tokio::main]
async fn main() {
    async fn add_url(State(db): State<Arc<UrlDAO>>, Json(payload): Json<serde_json::Value>) -> Json<UrlShorten> {
        let url = payload["url"].as_str().unwrap().to_string();
        let (url, short_url) = db.insert_url(url.clone()).await.unwrap();
        println!("Added URL: {} -> {}", url, short_url);
        Json(UrlShorten { url, short_url })
    }

    async fn get_full_url(State(db): State<Arc<UrlDAO>>, Path(short_url): Path<String>) -> Json<UrlShorten> {
        println!("Getting full URL for: {}", short_url);
        let full_url = db.get_url(short_url.clone()).await;
        match full_url {
            Ok(url) => {
                println!("Redirecting to: {}", url);
                Json(UrlShorten { url, short_url })
            }
            Err(e) => {
                println!("Error: {}", e);
                println!("Short URL not found: {}", short_url);
                Json(UrlShorten { url: "".to_string(), short_url })
            }
        }
    }
    let temp_db = NamedTempFile::new().expect("Failed to create temp file");
    let db_addr = temp_db.path().to_str().unwrap().to_string();
    let shared_state = Arc::new(UrlDAO::new(db_addr));
    // build our application with a single route
    let app = Router::new().route("/", get(|| async { "Hello, World!" }))
        .route("/add_url", post(add_url))
            .route("/get_full_url/:short_url", get(get_full_url))
        .with_state(shared_state);

    // run our app with hyper, listening globally on port 3000
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app).await.unwrap();
}
